import * as THREE from "three"

export default class LineSegmentsGeometry extends THREE.InstancedBufferGeometry {
  positionBuffer: any
  colorBuffer: any
  box: THREE.Box3
  tempVector: THREE.Vector3
  constructor() {
    super()
    this.type = "LineSegmentsGeometry"
    this.setIndex([0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5])
    this.setAttribute("position", new THREE.Float32BufferAttribute([-1, 2, 0, 1, 2, 0, -1, 1, 0, 1, 1, 0, -1, 0, 0, 1, 0, 0, -1, -1, 0, 1, -1, 0], 3))
    this.setAttribute("uv", new THREE.Float32BufferAttribute([0, 1, 0.5, 1, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0, 0, 1, 0.5, 1], 2))
  }
  applyMatrix(e) {
    const t = this.attributes.instanceStart
    const i = this.attributes.instanceEnd
    void 0 !== t && (t.applyMatrix4(e), i.applyMatrix4(e), (this.positionBuffer.needsUpdate = !0))
    null !== this.boundingBox && this.computeBoundingBox()
    null !== this.boundingSphere && this.computeBoundingSphere()
    return this
  }
  setPositions(e) {
    let t
    e instanceof Float32Array ? (t = e) : Array.isArray(e) && (t = new Float32Array(e))
    t &&
      (this.positionBuffer
        ? (this.positionBuffer.set(t, 0), (this.positionBuffer.needsUpdate = !0))
        : ((this.positionBuffer = new THREE.InstancedInterleavedBuffer(t, 6, 1)),
          this.setAttribute("instanceStart", new THREE.InterleavedBufferAttribute(this.positionBuffer, 3, 0, !1)),
          this.setAttribute("instanceEnd", new THREE.InterleavedBufferAttribute(this.positionBuffer, 3, 3, !1))),
      this.computeBoundingBox(),
      this.computeBoundingSphere())
    return this
  }
  setColors(e) {
    let t
    e instanceof Float32Array ? (t = e) : Array.isArray(e) && (t = new Float32Array(e))
    t &&
      (this.colorBuffer
        ? (this.colorBuffer.set(t, 0), (this.colorBuffer.needsUpdate = !0))
        : ((this.colorBuffer = new THREE.InstancedInterleavedBuffer(t, 6, 1)),
          this.setAttribute("instanceColorStart", new THREE.InterleavedBufferAttribute(this.colorBuffer, 3, 0, !1)),
          this.setAttribute("instanceColorEnd", new THREE.InterleavedBufferAttribute(this.colorBuffer, 3, 3, !1))))
    return this
  }
  fromWireframeGeometry(e) {
    this.setPositions(e.attributes.position.array)

    return this
  }
  fromEdgesGeometry(e) {
    this.setPositions(e.attributes.position.array)
    return this
  }
  fromMesh(e) {
    this.fromWireframeGeometry(new THREE.WireframeGeometry(e.geometry))
    return this
  }
  fromLineSegements(e) {
    const t = e.geometry
    t instanceof THREE.BufferGeometry && this.setPositions(t["position"].array)
    return this
  }
  computeBoundingBox() {
    this.boundingBox || (this.boundingBox = new THREE.Box3()), this.box || (this.box = new THREE.Box3())
    const e = this.attributes.instanceStart
    const t = this.attributes.instanceEnd
    void 0 !== e &&
      void 0 !== t &&
      (this.boundingBox.setFromBufferAttribute(e as any), this.box.setFromBufferAttribute(t as any), this.boundingBox.union(this.box))
  }
  computeBoundingSphere() {
    this.tempVector || (this.tempVector = new THREE.Vector3())
    this.boundingSphere || (this.boundingSphere = new THREE.Sphere())
    this.boundingBox || this.computeBoundingBox()
    const e = this.attributes.instanceStart
    const t = this.attributes.instanceEnd
    if (void 0 !== e && void 0 !== t) {
      const i = this.boundingSphere.center
      this.boundingBox.getCenter(i)
      let n = 0
      for (let s = 0, r = e.count; s < r; s++) {
        this.tempVector.fromBufferAttribute(e, s)
        n = Math.max(n, i.distanceToSquared(this.tempVector))
        this.tempVector.fromBufferAttribute(t, s)
        n = Math.max(n, i.distanceToSquared(this.tempVector))
      }
      this.boundingSphere.radius = Math.sqrt(n)
      isNaN(this.boundingSphere.radius) &&
        console.error("computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.", this)
    }
  }
}
